import threading
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.lines as line
import numpy as np
import random
import time
 


class PlotData():
    def __init__(self):
        # 定义画布
        self.fig = plt.figure(figsize=(10,6), dpi=80)
        self.ax = plt.subplot(211,ylim=(0,5))
        self.bx = plt.subplot(212,ylim=(0,5))
        self.line = line.Line2D([], [])  # 绘制直线

        self.obsX = []
        self.obsY = []

    # 初始化图像
    def plot_init(self):
        self.ax.add_line(line)
        return line, # 必须加逗号,否则会报错（TypeError: 'Line2D' object is not iterable）

    # 更新图像(animation会不断调用此函数刷新图像，实现动态图的效果)
    def plot_update(self, i):

        if len(self.obsX) < 100:
            self.ax.set_xlim(min(self.obsX),max(self.obsX)+30)  # 横坐标范围（横坐标的范围和刻度可根据数据长度更新）
        else:
            self.ax.set_xlim(self.obsX[-80],max(self.obsX) * 1.2)  # 横坐标范围（横坐标的范围和刻度可根据数据长度更新）
        
        self.ax.set_ylim(min(self.obsY), max(self.obsY)+10)  # 纵坐标范围（横坐标的范围和刻度可根据数据长度更新）
        self.ax.set_title("CPU Loading",fontsize=8)  # 设置title

        self.bx.set_ylim(min(self.obsY), max(self.obsY)+10)  # 纵坐标范围（横坐标的范围和刻度可根据数据长度更新）
        self.bx.set_title("Memory Loading",fontsize=8)  # 设置title

        self.line.set_xdata(np.array(self.obsX))  # 更新直线的数据
        self.line.set_ydata(np.array(self.obsY))  # 更新直线的数据
        # 大标题（若有多个子图，可为其设置大标题）
        plt.suptitle('System Loading',fontsize=8)
        # 重新渲染子图
        self.ax.figure.canvas.draw()  # 必须加入这一行代码，才能更新title和坐标!!!
        return line,  # 必须加逗号,否则会报错（TypeError: 'Line2D' object is not iterable

    def print_figure(self):
        # 绘制动态图
        ani = animation.FuncAnimation(self.fig,   # 画布
                                    self.plot_update,  # 图像更新
                                    init_func=self.plot_init,  # 图像初始化
                                    frames=1,
                                    interval=30,  # 图像更新间隔
                                    blit=True)
        
    # 数据更新函数
def dataUpdate_thead():
    global obsX
    global obsY
    i = 1
    while True:  # 为了方便测试，让数据不停的更新
        obsX.append(i)
        obsY.append(random.randrange(100, 200))
        i += 1
        time.sleep(1)
 
# 为数据更新函数单独创建一个线程，与图像绘制的线程并发执行
ad_rdy_ev = threading.Event()
ad_rdy_ev.set()  # 设置线程运行
t = threading.Thread(target=dataUpdate_thead, args=()) # 更新数据，参数说明：target是线程需要执行的函数，args是传递给函数的参数）
t.daemon = True
t.start()  # 线程执行

plt.show() # 显示图像